﻿using System.Collections.Generic;
using GameObjects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Network;
using GameObjects.DrawableClasses;
using GameObjects.Values;
using GameProcess;
using GameProcess.Actors;
using System.Text;

namespace StillAlive
{
    /// <summary>
    /// Здесь находится процесс игры (не меню)
    /// </summary>
    public class Battlefield : Microsoft.Xna.Framework.DrawableGameComponent
    {
        public static Battlefield Instance;

        SpriteBatch spriteBatch;
        // состояние игры
        public GameState gameState;
        // наш игрок
        RealCharacter player;
        // центр экрана
        Vector2 centerOfScreen;

        Communicator communicator;
        Sprite playerSprite;
        public SpriteFont font;
        public int PacketLength;

        public Battlefield(Game game)
            : base(game)
        {
        }
        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            GameState.CreateInstance(Owner.Client);
            gameState = GameState.Instance;
            gameState.CharacterAdded += new System.Action<RealCharacter>(CreateCharacter);

            Point playerSize = new Point(32, 32);
            centerOfScreen = new Vector2(Game.GraphicsDevice.Viewport.Width / 2,
                Game.GraphicsDevice.Viewport.Height / 2);
            Dimensions.ScreenSize = new Point(Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height);
            Dimensions.CenterOfTheScreen = new Point(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
            // текстуры
            Texture2D playerTexture = Game.Content.Load<Texture2D>(@"Images\player");
            playerSprite = new Sprite(
                playerTexture, playerSize, 0, Point.Zero, new Point(1, 1));
            // загрузка уровня
            Texture2D levelTexture = Game.Content.Load<Texture2D>(@"Images\level1");
            // текстуры лазера
            Textures.LazerTexture = Game.Content.Load<Texture2D>(@"Images\fire");
            Textures.RedTexture = Game.Content.Load<Texture2D>(@"Images\monster");
            Textures.HP = Game.Content.Load<Texture2D>(@"Images\hp");
            Textures.MP = Game.Content.Load<Texture2D>(@"Images\mp");
            communicator = new Communicator(out player);
            gameState.Level.Texture = levelTexture;
            Texture2D solidTexture = Game.Content.Load<Texture2D>(@"Images\solid");
            foreach (var solid in gameState.Level.Solids)
            {
                solid.Sprite = new Sprite(
                    solidTexture, solid.Size, 0, Point.Zero, new Point(1, 1));
            }
            // шрифты
            font = Game.Content.Load<SpriteFont>(@"Fonts\SpriteFont1");
            Styles.Instance.Font = font;

            base.LoadContent();
        }

        // создаём персонажа
        public void CreateCharacter(RealCharacter character)
        {
            character.Sprite = playerSprite;
        }

        public void RemoveCharacter(int playerId)
        {
            gameState.RemoveCharacter(playerId);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            gameState.Update(gameTime);

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
            // рисуем карту и объекты
            Vector2 levelPos = centerOfScreen - player.Position;
            gameState.Level.Draw(spriteBatch, levelPos);
            foreach (var solid in gameState.Level.Solids)
            {
                solid.Draw(gameTime, spriteBatch, levelPos);
            }

            // рисуем игрока
            player.Draw(gameTime, spriteBatch, centerOfScreen);
            lock (gameState.Players)
            {
                foreach (var character in gameState.Players.Values)
                {
                    if (character != player)
                        character.Draw(gameTime, spriteBatch, character.Position + levelPos);
                }
            }
            string text = PacketLength == 0 ? "No connection." : "Packet length: " + PacketLength;
            spriteBatch.DrawString(font, text, new Vector2(10, 10), Color.Black,
                0, Vector2.Zero, 1, SpriteEffects.None, 1);

            // статистика игры
            if (Commands.ScoresButtonPressed && gameState.Scores != null)
            {
                StringBuilder scoresText = new StringBuilder();
                foreach (var score in gameState.Scores)
                {
                    scoresText.AppendFormat("Player {0}    Kills: {1}    Deaths: {2}\n", score.Key, score.Value.Kills, score.Value.Deaths);
                }
                spriteBatch.DrawString(font, scoresText.ToString(), new Vector2(10, 50), Color.Black,
                    0, Vector2.Zero, 1, SpriteEffects.None, 1);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

        protected override void Dispose(bool disposing)
        {
            communicator.Stop();
            base.Dispose(disposing);
        }
    }
}
